﻿
// Проверка замыкающих комментариев в окончаниях методов и областей

Перем Типы;
Перем Токены;
Перем Исходник;
Перем ТаблицаТокенов;
Перем ТаблицаОшибок;
Перем ТаблицаЗамен;

Перем УровеньОбласти;
Перем СтекОбластей;

Процедура Открыть(Парсер, Параметры) Экспорт

	Типы = Парсер.Типы();
	Токены = Парсер.Токены();
	Исходник = Парсер.Исходник();
	ТаблицаТокенов = Парсер.ТаблицаТокенов();
	ТаблицаОшибок = Парсер.ТаблицаОшибок();
	ТаблицаЗамен = Парсер.ТаблицаЗамен();
	
	УровеньОбласти = 0;
	СтекОбластей = Новый Соответствие;

КонецПроцедуры

Функция Закрыть() Экспорт
	Возврат Неопределено;
КонецФункции

Функция Подписки() Экспорт
	Перем Подписки;
	Подписки = Новый Массив;
	Подписки.Добавить("ПосетитьОбъявлениеМетода");
	Подписки.Добавить("ПосетитьИнструкциюПрепроцессора");
	Возврат Подписки;
КонецФункции

Процедура ПосетитьОбъявлениеМетода(ОбъявлениеМетода) Экспорт

	СледующийТокен = ТаблицаТокенов[ОбъявлениеМетода.Конец.Индекс + 1];

	Если СледующийТокен.Токен = Токены.Комментарий
		И СледующийТокен.НомерСтроки = ОбъявлениеМетода.Конец.НомерСтроки Тогда

		Комментарий = СокрП(Сред(Исходник, СледующийТокен.Позиция, СледующийТокен.Длина));
		ПравильныйКомментарий = СтрШаблон(" %1%2", ОбъявлениеМетода.Сигнатура.Имя, "()"); 
		
		Если Комментарий <> ПравильныйКомментарий Тогда
			Ошибка("Замыкающий комментарий неактуален", СледующийТокен,, Истина);
			Замена(ПравильныйКомментарий, СледующийТокен);
		КонецЕсли;

	КонецЕсли;

КонецПроцедуры

Процедура ПосетитьИнструкциюПрепроцессора(ИнструкцияПрепроцессора) Экспорт

	Если ИнструкцияПрепроцессора.Тип = Типы.ИнструкцияПрепроцессораОбласть Тогда

		УровеньОбласти = УровеньОбласти + 1;
		СтекОбластей[УровеньОбласти] = ИнструкцияПрепроцессора.Имя;

	ИначеЕсли ИнструкцияПрепроцессора.Тип = Типы.ИнструкцияПрепроцессораКонецОбласти Тогда
		СледующийТокен = ТаблицаТокенов[ИнструкцияПрепроцессора.Конец.Индекс + 1];

		Если СледующийТокен.Токен = Токены.Комментарий
			И СледующийТокен.НомерСтроки = ИнструкцияПрепроцессора.Конец.НомерСтроки Тогда

			Комментарий = СокрП(Сред(Исходник, СледующийТокен.Позиция, СледующийТокен.Длина));
			ИмяОбласти = СтекОбластей[УровеньОбласти];
			ПравильныйКомментарий = СтрШаблон(" %1", ИмяОбласти);
			
			Если Комментарий <> ПравильныйКомментарий Тогда
				Ошибка("Замыкающий комментарий неактуален", СледующийТокен,, Истина);
				Замена(ПравильныйКомментарий, СледующийТокен);
			КонецЕсли;

		КонецЕсли;

		УровеньОбласти = УровеньОбласти - 1;

	КонецЕсли;

КонецПроцедуры

Процедура Ошибка(Текст, Начало, Конец = Неопределено, ЕстьЗамена = Ложь)
	Ошибка = ТаблицаОшибок.Добавить();
	Ошибка.Источник = "ДетекторОшибочныхЗамыкающихКомментариев";
	Ошибка.Текст = Текст;
	Ошибка.ПозицияНачала = Начало.Позиция;
	Ошибка.НомерСтрокиНачала = Начало.НомерСтроки;
	Ошибка.НомерКолонкиНачала = Начало.НомерКолонки;
	Если Конец = Неопределено Или Конец = Начало Тогда
		Ошибка.ПозицияКонца = Начало.Позиция + Начало.Длина;
		Ошибка.НомерСтрокиКонца = Начало.НомерСтроки;
		Ошибка.НомерКолонкиКонца = Начало.НомерКолонки + Начало.Длина;
	Иначе
		Ошибка.ПозицияКонца = Конец.Позиция + Конец.Длина;
		Ошибка.НомерСтрокиКонца = Конец.НомерСтроки;
		Ошибка.НомерКолонкиКонца = Конец.НомерКолонки + Конец.Длина;
	КонецЕсли;
	Ошибка.ЕстьЗамена = ЕстьЗамена;
КонецПроцедуры

Процедура Замена(Текст, Начало, Конец = Неопределено)
	НоваяЗамена = ТаблицаЗамен.Добавить();
	НоваяЗамена.Источник = "ДетекторОшибочныхЗамыкающихКомментариев";
	НоваяЗамена.Текст = Текст;
	НоваяЗамена.Позиция = Начало.Позиция;
	Если Конец = Неопределено Тогда
		НоваяЗамена.Длина = Начало.Длина;
	Иначе
		НоваяЗамена.Длина = Конец.Позиция + Конец.Длина - Начало.Позиция;
	КонецЕсли;
КонецПроцедуры